<!DOCTYPE html>
<html lang="zh-cn" color-mode="light">

  <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="keywords" content="" />
  <meta name="author" content="郁涛丶" />
  <meta name="description" content="" />
  
  
  <title>
    
      MIT6S081lab 
      
      
      |
    
     郁涛丶&#39;s Blog
  </title>

  
    <link rel="apple-touch-icon" href="/images/favicon.png">
    <link rel="icon" href="/images/favicon.png">
  

  <!-- Raleway-Font -->
  <link href="https://fonts.googleapis.com/css?family=Raleway&display=swap" rel="stylesheet">

  <!-- hexo site css -->
  
<link rel="stylesheet" href="/css/color-scheme.css">
<link rel="stylesheet" href="/css/base.css">
<link rel="stylesheet" href="//at.alicdn.com/t/font_1886449_67xjft27j1l.css">
<link rel="stylesheet" href="/css/github-markdown.css">
<link rel="stylesheet" href="/css/highlight.css">
<link rel="stylesheet" href="/css/comments.css">

  <!-- 代码块风格 -->
  
    
<link rel="stylesheet" href="/css/figcaption/mac-block.css">

  

  <!-- jquery3.3.1 -->
  
    <script defer type="text/javascript" src="/plugins/jquery.min.js"></script>
  

  <!-- fancybox -->
  
    <link href="/plugins/jquery.fancybox.min.css" rel="stylesheet">
    <script defer type="text/javascript" src="/plugins/jquery.fancybox.min.js"></script>
  
  
<script src="/js/fancybox.js"></script>


  

  <script>
    var html = document.documentElement
    const colorMode = localStorage.getItem('color-mode')
    if (colorMode) {
      document.documentElement.setAttribute('color-mode', colorMode)
    }
  </script>
<!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/atom.xml" title="郁涛丶's Blog" type="application/atom+xml">
</head>


  <body>
    <div id="app">
      <div class="header">
  <div class="avatar">
    <a href="/">
      <!-- 头像取消懒加载，添加no-lazy -->
      
        <img src="/images/avatar.png" alt="">
      
    </a>
    <div class="nickname"><a href="/">Ghostasky</a></div>
  </div>
  <div class="navbar">
    <ul>
      
        <li class="nav-item" data-path="/">
          <a href="/">Home</a>
        </li>
      
        <li class="nav-item" data-path="/archives/">
          <a href="/archives/">Archives</a>
        </li>
      
        <li class="nav-item" data-path="/categories/">
          <a href="/categories/">Categories</a>
        </li>
      
        <li class="nav-item" data-path="/tags/">
          <a href="/tags/">Tags</a>
        </li>
      
        <li class="nav-item" data-path="/about/">
          <a href="/about/">About</a>
        </li>
      
    </ul>
  </div>
</div>


<script src="/js/activeNav.js"></script>



      <div class="flex-container">
        <!-- 文章详情页，展示文章具体内容，url形式：https://yoursite/文章标题/ -->
<!-- 同时为「标签tag」，「朋友friend」，「分类categories」，「关于about」页面的承载页面，具体展示取决于page.type -->


    <!-- LaTex Display -->

  
    <script async type="text/javascript" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
  
  <script>
    MathJax = {
      tex: {
        inlineMath: [['$', '$'], ['\\(', '\\)']]
      }
    }
  </script>


        
            
                <!-- clipboard -->

  
    <script async type="text/javascript" src="/plugins/clipboard.min.js"></script>
  
  
<script src="/js/codeCopy.js"></script>



                    
                        
                                
                                        
                                                
                                                        
                                                            <!-- 文章内容页 url形式：https://yoursite/文章标题/ -->
                                                            <div class="container post-details" id="post-details">
                                                                <div class="post-content">
                                                                    <div class="post-title">
                                                                        MIT6S081lab
                                                                    </div>
                                                                    <div class="post-attach">
                                                                        <span class="post-pubtime">
        <i class="iconfont icon-updatetime" title="Update time"></i>
        2022-07-10
      </span>

                                                                        <span class="post-pubtime"> 本文共4.3k字 </span>

                                                                        <span class="post-pubtime">
        大约需要32min
      </span>

                                                                        
                                                                                    <span class="post-categories">
        <i class="iconfont icon-bookmark" title="Categories"></i>
        
        <span class="span--category">
          <a href="/categories/Technology/" title="Technology">
            <b>#</b> Technology
          </a>
        </span>
                                                                                    
                                                                                        </span>
                                                                                        
                                                                            <span class="post-tags">
        <i class="iconfont icon-tags" title="Tags"></i>
        
        <span class="span--tag">
          <a href="/tags/OS/" title="OS">
            <b>#</b> OS
          </a>
        </span>
                                                                            
                                                                                </span>
                                                                                
                                                                    </div>
                                                                    <div class="markdown-body">
                                                                        <p>写oslab的一些代码，</p>
<blockquote>
<p>  xv6中文文档：<a target="_blank" rel="noopener" href="https://th0ar.gitbooks.io/xv6-chinese/content/content/chapter2.html">https://th0ar.gitbooks.io/xv6-chinese/content/content/chapter2.html</a></p>
</blockquote>
<p>[toc]</p>
<h1 id="进度"><a href="#进度" class="headerlink" title="进度"></a>进度</h1><p>进度：</p>
<table>
<thead>
<tr>
<th align="left">lab_num&#x2F;lab_name</th>
<th align="left">Is it completed</th>
</tr>
</thead>
<tbody><tr>
<td align="left">Lab1&#x2F;sleep</td>
<td align="left">Finish</td>
</tr>
<tr>
<td align="left">Lab1&#x2F;pingpong</td>
<td align="left">Finish</td>
</tr>
<tr>
<td align="left">Lab1&#x2F;prime</td>
<td align="left">Finish</td>
</tr>
<tr>
<td align="left">Lab1&#x2F;find</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Lab1&#x2F;xargs</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Lab2&#x2F;trace</td>
<td align="left">Finish</td>
</tr>
<tr>
<td align="left">Lab2&#x2F;sysinfo</td>
<td align="left">Finish</td>
</tr>
<tr>
<td align="left">Lab3&#x2F;vmprint</td>
<td align="left">Finish</td>
</tr>
</tbody></table>
<h1 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h1><p>之前搞到一半，，环境有点问题，想着重新搞个虚拟机写os的lab</p>
<p>依赖，源码：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install git build-essential gdb-multiarch qemu-system-misc gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu </span><br><span class="line"></span><br><span class="line">sudo apt-get remove qemu-system-misc</span><br><span class="line">sudo apt-get install qemu-system-misc=1:4.2-3ubuntu6</span><br><span class="line">sudo apt install gcc-riscv64-unknown-elf</span><br><span class="line">git clone git://g.csail.mit.edu/xv6-labs-2020</span><br></pre></td></tr></table></figure>

<p>有如下分支：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">yutao@ubuntu:~/xv6-labs-2020$ git branch  --remote</span><br><span class="line">  origin/HEAD -&gt; origin/master</span><br><span class="line">  origin/cow</span><br><span class="line">  origin/fs</span><br><span class="line">  origin/lazy</span><br><span class="line">  origin/lock</span><br><span class="line">  origin/master</span><br><span class="line">  origin/mmap</span><br><span class="line">  origin/net</span><br><span class="line">  origin/pgtbl</span><br><span class="line">  origin/riscv</span><br><span class="line">  origin/syscall</span><br><span class="line">  origin/thread</span><br><span class="line">  origin/traps</span><br><span class="line">  origin/util</span><br></pre></td></tr></table></figure>

<p>调试的话要在Makefile里加：</p>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">gdb:</span></span><br><span class="line">	riscv64-unknown-elf-gdb kernel/kernel</span><br></pre></td></tr></table></figure>

<p>调试的话：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">gdb-multiarch  kernel/kernel</span><br><span class="line">make qemu-gdb</span><br></pre></td></tr></table></figure>

<p>评测脚本grade-lab-util是python程序，这里对第一行进行修改，将</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">PYTHON</span><br><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br></pre></td></tr></table></figure>

<p>修改为：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">PYTHON</span><br><span class="line"><span class="comment">#!/usr/bin python</span></span><br></pre></td></tr></table></figure>

<p>还要再Makefile里面加。</p>
<h2 id="分支建议："><a href="#分支建议：" class="headerlink" title="分支建议："></a>分支建议：</h2><p>(6). <strong>xv6实验git分支建议</strong></p>
<p>建议是每个实验创建一个测试分支，例如对于<strong>util</strong>来说</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git checkout util         <span class="comment"># 切换到util分支</span></span><br><span class="line">git checkout -b util_test <span class="comment"># 建立并切换到util的测试分支</span></span><br></pre></td></tr></table></figure>

<p>当你在**<em>util_test*<strong>分支中每测试通过一个作业，请提交（<code>git commit</code>）你的代码，并将所做的修改合并（<code>git merge</code>）到</strong></em>util***中，然后提交（<code>git push</code>）到github</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">git add .</span><br><span class="line">git commit -m <span class="string">&quot;完成了第一个作业&quot;</span></span><br><span class="line">git checkout util</span><br><span class="line">git merge util_test</span><br><span class="line">git push github util:util</span><br></pre></td></tr></table></figure>

<h1 id="lab1"><a href="#lab1" class="headerlink" title="lab1"></a>lab1</h1><p>实验指导书：<a target="_blank" rel="noopener" href="https://pdos.csail.mit.edu/6.828/2020/labs/util.html">https://pdos.csail.mit.edu/6.828/2020/labs/util.html</a></p>
<h2 id="sleep"><a href="#sleep" class="headerlink" title="sleep"></a>sleep</h2><p>代码：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;kernel/types.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;kernel/stat.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;user/user.h&quot;</span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> **argv)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> n;</span><br><span class="line">    <span class="keyword">if</span> (argc != <span class="number">2</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;please enter a number!&quot;</span>);</span><br><span class="line">        <span class="built_in">exit</span>(<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        n = atoi( argv[<span class="number">1</span>]);</span><br><span class="line">        sleep(n);</span><br><span class="line">        <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">yutao@ubuntu:~/xv6-<span class="built_in">labs</span><span class="number">-2020</span>$ sudo python3 grade-lab-util sleep</span><br><span class="line">make: <span class="string">&#x27;kernel/kernel&#x27;</span> is up to date.</span><br><span class="line">== Test sleep, no arguments == sleep, no arguments: OK (<span class="number">1.6</span>s) </span><br><span class="line">== Test sleep, returns == sleep, returns: OK (<span class="number">1.0</span>s) </span><br><span class="line">== Test sleep, makes syscall == sleep, makes syscall: OK (<span class="number">0.9</span>s) </span><br></pre></td></tr></table></figure>

<h2 id="pingpong"><a href="#pingpong" class="headerlink" title="pingpong"></a>pingpong</h2><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #include &lt;stdio.h&gt;</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;kernel/types.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;user/user.h&quot;</span></span></span><br><span class="line"><span class="comment">// 编写一个程序，使用UNIX系统调用在一对管道上的两</span></span><br><span class="line"><span class="comment">// 个进程之间“乒乓”一个字节，每个方向一个。父级应向子</span></span><br><span class="line"><span class="comment">// 级发送一个字节；子进程应该打印“：received ping”，</span></span><br><span class="line"><span class="comment">// 其中是其进程ID，将管道上的字节写入父进程，然后退出；</span></span><br><span class="line"><span class="comment">// 父进程应该从子进程读取字节，打印“：received pong”，</span></span><br><span class="line"><span class="comment">// 然后退出。您的解决方案应该在文件“user/pingpong.c”中。</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> READEND 0</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> WRITTEND 1</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> p[<span class="number">2</span>];</span><br><span class="line">    <span class="keyword">int</span> pid;</span><br><span class="line">    <span class="keyword">char</span> buf[<span class="number">2</span>];</span><br><span class="line">    <span class="keyword">char</span> *parmsg = <span class="string">&quot;a&quot;</span>;</span><br><span class="line">    <span class="keyword">char</span> *chimsg = <span class="string">&quot;b&quot;</span>;</span><br><span class="line"></span><br><span class="line">    pipe(p);</span><br><span class="line"></span><br><span class="line">    pid = fork();</span><br><span class="line">    <span class="keyword">if</span> (pid &lt; <span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">exit</span>(<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span> (pid == <span class="number">0</span>) <span class="comment">// child processs</span></span><br><span class="line">    &#123;</span><br><span class="line">        read(p[READEND], buf, <span class="number">1</span>);</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;child receive: %c\n&quot;</span>, buf[<span class="number">0</span>]);</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;%d: received ping\n&quot;</span>, getpid());</span><br><span class="line">        write(p[WRITTEND], chimsg, <span class="number">1</span>);</span><br><span class="line">        close(p[READEND]);</span><br><span class="line">        close(p[WRITTEND]);</span><br><span class="line"></span><br><span class="line">        <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        write(p[WRITTEND], parmsg, <span class="number">1</span>);</span><br><span class="line">        wait(<span class="number">0</span>);</span><br><span class="line">        read(p[READEND], buf, <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;parent receive: %c\n&quot;</span>, buf[<span class="number">0</span>]);</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;%d: received pong\n&quot;</span>, getpid());</span><br><span class="line">        close(p[WRITTEND]);</span><br><span class="line">        close(p[READEND]);</span><br><span class="line">        <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// yutao@ubuntu:~/xv6-labs-2020$ sudo python3 grade-lab-util pingpong</span></span><br><span class="line"><span class="comment">// make: &#x27;kernel/kernel&#x27; is up to date.</span></span><br><span class="line"><span class="comment">// == Test pingpong == pingpong: OK (1.9s)</span></span><br></pre></td></tr></table></figure>



<h2 id="prime"><a href="#prime" class="headerlink" title="prime"></a>prime</h2><p>使用的方法是埃拉托斯特尼素数筛，简称筛法。简单地说就是，每次得到一个素数时，在所有小于 n 的数中，删除它的倍数，然后不断迭代，剩下的就全是素数了。</p>
<p><img src="/2022/07/10/2022-7-10-oslab/sieve.gif"></p>
<h1 id="Lab2-system-calls"><a href="#Lab2-system-calls" class="headerlink" title="Lab2 system calls"></a>Lab2 system calls</h1><blockquote>
<p>  实验指导书：<a target="_blank" rel="noopener" href="https://pdos.csail.mit.edu/6.828/2020/labs/syscall.html">https://pdos.csail.mit.edu/6.828/2020/labs/syscall.html</a></p>
</blockquote>
<p>需要读xv6book的第2章、4.3、4.4.</p>
<p>用户空间的系统调用在：<code>user/user.h和user/usys.pl</code></p>
<p>kernel空间的系统调用在：<code>kernel/kernel.h和kernel/syscall.c</code></p>
<p>与process相关的代码在：<code>kernel/proc.h &amp;&amp; kernel/proc.c</code></p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git checkout syscall</span><br><span class="line">$ make clean</span><br></pre></td></tr></table></figure>



<h2 id="System-call-tracing"><a href="#System-call-tracing" class="headerlink" title="System call tracing"></a>System call tracing</h2><blockquote>
<p>  In this assignment you will add a system call tracing feature that may help you when debugging later labs. You’ll create a new trace system call that will control tracing. It should take one argument, an integer “mask”, whose bits specify which system calls to trace. For example, to trace the fork system call, a program calls trace(1 &lt;&lt; SYS_fork), where SYS_fork is a syscall number from kernel&#x2F;syscall.h. You have to modify the xv6 kernel to print out a line when each system call is about to return, if the system call’s number is set in the mask. The line should contain the process id, the name of the system call and the return value; you don’t need to print the system call arguments. The trace system call should enable tracing for the process that calls it and any children that it subsequently forks, but should not affect other processes.</p>
</blockquote>
<p>示例：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">$ trace <span class="number">32</span> grep hello README</span><br><span class="line"><span class="number">3</span>: syscall read -&gt; <span class="number">1023</span></span><br><span class="line"><span class="number">3</span>: syscall read -&gt; <span class="number">966</span></span><br><span class="line"><span class="number">3</span>: syscall read -&gt; <span class="number">70</span></span><br><span class="line"><span class="number">3</span>: syscall read -&gt; <span class="number">0</span></span><br><span class="line">$</span><br><span class="line">$ trace <span class="number">2147483647</span> grep hello README</span><br><span class="line"><span class="number">4</span>: syscall trace -&gt; <span class="number">0</span></span><br><span class="line"><span class="number">4</span>: syscall exec -&gt; <span class="number">3</span></span><br><span class="line"><span class="number">4</span>: syscall open -&gt; <span class="number">3</span></span><br><span class="line"><span class="number">4</span>: syscall read -&gt; <span class="number">1023</span></span><br><span class="line"><span class="number">4</span>: syscall read -&gt; <span class="number">966</span></span><br><span class="line"><span class="number">4</span>: syscall read -&gt; <span class="number">70</span></span><br><span class="line"><span class="number">4</span>: syscall read -&gt; <span class="number">0</span></span><br><span class="line"><span class="number">4</span>: syscall close -&gt; <span class="number">0</span></span><br><span class="line">$</span><br><span class="line">$ grep hello README</span><br><span class="line">$</span><br><span class="line">$ trace <span class="number">2</span> usertests forkforkfork</span><br><span class="line">usertests starting</span><br><span class="line">test forkforkfork: <span class="number">407</span>: syscall fork -&gt; <span class="number">408</span></span><br><span class="line"><span class="number">408</span>: syscall fork -&gt; <span class="number">409</span></span><br><span class="line"><span class="number">409</span>: syscall fork -&gt; <span class="number">410</span></span><br><span class="line"><span class="number">410</span>: syscall fork -&gt; <span class="number">411</span></span><br><span class="line"><span class="number">409</span>: syscall fork -&gt; <span class="number">412</span></span><br><span class="line"><span class="number">410</span>: syscall fork -&gt; <span class="number">413</span></span><br><span class="line"><span class="number">409</span>: syscall fork -&gt; <span class="number">414</span></span><br><span class="line"><span class="number">411</span>: syscall fork -&gt; <span class="number">415</span></span><br><span class="line">...</span><br><span class="line">$</span><br></pre></td></tr></table></figure>

<blockquote>
<p>  In the first example above, trace invokes grep tracing just the read system call. The 32 is 1&lt;&lt;SYS_read. In the second example, trace runs grep while tracing all system calls; the 2147583647 has all 31 low bits set. In the third example, the program isn’t traced, so no trace output is printed. In the fourth example, the fork system calls of all the descendants of the forkforkfork test in usertests are being traced. Your solution is correct if your program behaves as shown above (though the process IDs may be different).</p>
</blockquote>
<p>在这个实验里，我们需要让内核输出每个mask变量指定的系统函数的调用情况，格式为：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;pid&gt;: syscall &lt;syscall_name&gt; -&gt; &lt;return_value&gt;</span><br></pre></td></tr></table></figure>

<h3 id="hints"><a href="#hints" class="headerlink" title="hints"></a>hints</h3><ol>
<li>Add <code>$U/_trace</code> to UPROGS in Makefile</li>
<li>添加声明到<code>user/user.h</code>中</li>
<li>添加一个<code>entry</code>到<code>user/usys.pl</code></li>
<li>添加一个syscall number到<code>kernel/syscall.h</code>中</li>
<li>添加<code>sys_trace()</code>函数到<code>kernel/sysproc.c</code>中</li>
<li>修改<code>kernel/proc.h</code>中的proc结构体(记录当前进程信息)，添加一个mask值，用来识别system number</li>
</ol>
<p>proc结构体：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Per-process state</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">proc</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">spinlock</span> <span class="title">lock</span>;</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// p-&gt;lock must be held when using these:</span></span><br><span class="line">  <span class="class"><span class="keyword">enum</span> <span class="title">procstate</span> <span class="title">state</span>;</span> <span class="comment">// Process state</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">proc</span> *<span class="title">parent</span>;</span>  <span class="comment">// Parent process</span></span><br><span class="line">  <span class="keyword">void</span> *chan;           <span class="comment">// If non-zero, sleeping on chan</span></span><br><span class="line">  <span class="keyword">int</span> killed;           <span class="comment">// If non-zero, have been killed</span></span><br><span class="line">  <span class="keyword">int</span> xstate;           <span class="comment">// Exit status to be returned to parent&#x27;s wait</span></span><br><span class="line">  <span class="keyword">int</span> pid;              <span class="comment">// Process ID</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// these are private to the process, so p-&gt;lock need not be held.</span></span><br><span class="line">  uint64 kstack;               <span class="comment">// Virtual address of kernel stack</span></span><br><span class="line">  uint64 sz;                   <span class="comment">// Size of process memory (bytes)</span></span><br><span class="line">  <span class="keyword">pagetable_t</span> pagetable;       <span class="comment">// User page table</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">trapframe</span> *<span class="title">trapframe</span>;</span> <span class="comment">// data page for trampoline.S</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">context</span> <span class="title">context</span>;</span>      <span class="comment">// swtch() here to run process</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">file</span> *<span class="title">ofile</span>[<span class="title">NOFILE</span>];</span>  <span class="comment">// Open files</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">inode</span> *<span class="title">cwd</span>;</span>           <span class="comment">// Current directory</span></span><br><span class="line">  <span class="keyword">char</span> name[<span class="number">16</span>];               <span class="comment">// Process name (debugging)</span></span><br><span class="line">  <span class="keyword">int</span> mask;                    <span class="comment">// system call</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>sys_trace具体实现</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">uint64 <span class="title">sys_trace</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">int</span> n;</span><br><span class="line">	<span class="comment">// argint检索的是第n个系统调用的参数，因此不包括系统调用本身，传入的参数为0</span></span><br><span class="line">	<span class="keyword">if</span> (argint(<span class="number">0</span>, &amp;n) &lt; <span class="number">0</span>)</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	myproc()-&gt;mask = n;</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>修改<code>kernel/proc.c</code>中的<code>fork</code>函数，添加子进程复制父进程mask：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">np-&gt;mask = p-&gt;mask;</span><br></pre></td></tr></table></figure>

<p>修改<code>kernel/syscall.c</code>，添加<code>SYS_trace</code>的声明，之后加到syscall的数组中，然后添加trace的识别功能。</p>
<p><code>p-&gt;trapframe-&gt;a0</code>中存放的是函数调用的返回值。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">extern</span> uint64 <span class="title">sys_trace</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="title">uint64</span> <span class="params">(*syscalls[])</span><span class="params">(<span class="keyword">void</span>)</span> </span>= &#123;</span><br><span class="line">	.....</span><br><span class="line">	[SYS_close] sys_close,</span><br><span class="line">	[SYS_trace] sys_trace,</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">char</span> *sysCallName[<span class="number">23</span>] = &#123;<span class="string">&quot;&quot;</span>, <span class="string">&quot;fork&quot;</span>, <span class="string">&quot;exit&quot;</span>, <span class="string">&quot;wait&quot;</span>, <span class="string">&quot;pipe&quot;</span>, <span class="string">&quot;read&quot;</span>, <span class="string">&quot;kill&quot;</span>, <span class="string">&quot;exec&quot;</span>,</span><br><span class="line">						 <span class="string">&quot;fstat&quot;</span>, <span class="string">&quot;chdir&quot;</span>, <span class="string">&quot;dup&quot;</span>, <span class="string">&quot;getpid&quot;</span>, <span class="string">&quot;sbrk&quot;</span>, <span class="string">&quot;sleep&quot;</span>, <span class="string">&quot;uptime&quot;</span>,</span><br><span class="line">						 <span class="string">&quot;open&quot;</span>, <span class="string">&quot;write&quot;</span>, <span class="string">&quot;mknod&quot;</span>, <span class="string">&quot;unlink&quot;</span>, <span class="string">&quot;link&quot;</span>, <span class="string">&quot;mkdir&quot;</span>, <span class="string">&quot;close&quot;</span>, <span class="string">&quot;trace&quot;</span>&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">syscall</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">int</span> num;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">proc</span> *<span class="title">p</span> =</span> myproc();</span><br><span class="line"></span><br><span class="line">	num = p-&gt;trapframe-&gt;a7;</span><br><span class="line">	<span class="keyword">if</span> (num &gt; <span class="number">0</span> &amp;&amp; num &lt; NELEM(syscalls) &amp;&amp; syscalls[num])</span><br><span class="line">	&#123;</span><br><span class="line">		p-&gt;trapframe-&gt;a0 = syscalls[num]();</span><br><span class="line">		<span class="keyword">if</span> (p-&gt;mask &amp; (<span class="number">1</span> &lt;&lt; num))</span><br><span class="line">		&#123;</span><br><span class="line">			<span class="built_in">printf</span>(<span class="string">&quot;%d: syscall %s -&gt; %d\n&quot;</span>, p-&gt;pid, sysCallName[num], p-&gt;trapframe-&gt;a0);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">else</span></span><br><span class="line">	&#123;</span><br><span class="line">		<span class="built_in">printf</span>(<span class="string">&quot;%d %s: unknown sys call %d\n&quot;</span>,</span><br><span class="line">			   p-&gt;pid, p-&gt;name, num);</span><br><span class="line">		p-&gt;trapframe-&gt;a0 = <span class="number">-1</span>;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">yutao@ubuntu:~/xv6-labs-2020$ sudo python3 grade-lab-syscall trace</span><br><span class="line">make: <span class="string">&#x27;kernel/kernel&#x27;</span> is up to date.</span><br><span class="line">== Test trace 32 grep == trace 32 grep: OK (1.4s) </span><br><span class="line">== Test trace all grep == trace all grep: OK (1.0s) </span><br><span class="line">== Test trace nothing == trace nothing: OK (1.0s) </span><br><span class="line">== Test trace children == trace children: OK (12.1s) </span><br></pre></td></tr></table></figure>

<h2 id="Sysinfo"><a href="#Sysinfo" class="headerlink" title="Sysinfo"></a>Sysinfo</h2><blockquote>
<p>  <a target="_blank" rel="noopener" href="https://github.com/whileskies/xv6-labs-2020/blob/main/doc/Lab2-system%20calls.md">https://github.com/whileskies/xv6-labs-2020/blob/main/doc/Lab2-system%20calls.md</a></p>
</blockquote>
<blockquote>
<p>  In this assignment you will add a system call, sysinfo, that collects information about the running system. The system call takes one argument: a pointer to a struct sysinfo (see kernel&#x2F;sysinfo.h). The kernel should fill out the fields of this struct: the freemem field should be set to the number of bytes of free memory, and the nproc field should be set to the number of processes whose state is not UNUSED. We provide a test program sysinfotest; you pass this assignment if it prints “sysinfotest: OK”.</p>
</blockquote>
<p>添加一个系统调用<code>sysinfo</code>，用于收集有关正在运行的系统的信息。系统调用采用一个参数：指向结构<code>sysinfo</code>的指针（参见<code>kernel/sysinfo.h</code>）。内核应填写此结构的字段：<code>freemem</code>字段应设置为可用内存的字节数，<code>nproc</code>字段应设置为其状态未使用的进程数。提供了一个测试程序sysinfotest；如果输出“sysinfotest:OK”，则通过此分配。</p>
<ol>
<li>添加<code>$U/_sysinfotest\</code></li>
<li>添加函数声明到<code>user.h</code>，添加<code>entry</code>到<code>usys.pl</code>，添加<code>syscall number</code>到<code>syscall.h</code>，然后加入到<code>syscall</code>函数数组中</li>
<li>然后为了添加<code>sys_sysinfo</code>函数到<code>kernel/sysproc.c</code>，这里为了实现需要在<code>kernel/proc.c</code>和<code>kernel/kalloc.c</code>中分别添加函数获取正在使用的进程和可用的内存数，然后记得将添加的函数声明在<code>defs.h</code></li>
<li>然后实现<code>sys_sysinfo</code>函数，这里需要看一下<code>copyout</code>函数的使用方法(参考<code>sys_fstat(kernel/sysfile.c)</code>和<code>filestat(kernel/file.c)</code>)</li>
</ol>
<p>添加函数声明：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">sysinfo</span>;</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">sysinfo</span><span class="params">(struct sysinfo *)</span></span>;</span><br></pre></td></tr></table></figure>

<p>添加<code>entry</code>：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">entry(<span class="string">&quot;sysinfo&quot;</span>);</span><br></pre></td></tr></table></figure>

<p>添加<code>syscall</code>：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//syscall.h</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> SYS_sysinfo 23</span></span><br></pre></td></tr></table></figure>

<p>加到<code>syscallname</code>的数组中：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">extern</span> uint64 <span class="title">sys_sysinfo</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br><span class="line"><span class="comment">//还有syscalls的数组也要加</span></span><br><span class="line"><span class="keyword">char</span> *sysCallName[<span class="number">24</span>] = &#123;<span class="string">&quot;&quot;</span>, <span class="string">&quot;fork&quot;</span>, <span class="string">&quot;exit&quot;</span>, <span class="string">&quot;wait&quot;</span>, <span class="string">&quot;pipe&quot;</span>, <span class="string">&quot;read&quot;</span>, <span class="string">&quot;kill&quot;</span>, <span class="string">&quot;exec&quot;</span>,</span><br><span class="line">						 <span class="string">&quot;fstat&quot;</span>, <span class="string">&quot;chdir&quot;</span>, <span class="string">&quot;dup&quot;</span>, <span class="string">&quot;getpid&quot;</span>, <span class="string">&quot;sbrk&quot;</span>, <span class="string">&quot;sleep&quot;</span>, <span class="string">&quot;uptime&quot;</span>,</span><br><span class="line">						 <span class="string">&quot;open&quot;</span>, <span class="string">&quot;write&quot;</span>, <span class="string">&quot;mknod&quot;</span>, <span class="string">&quot;unlink&quot;</span>, <span class="string">&quot;link&quot;</span>, <span class="string">&quot;mkdir&quot;</span>, <span class="string">&quot;close&quot;</span>, <span class="string">&quot;trace&quot;</span>, <span class="string">&quot;sysinfo&quot;</span>&#125;;</span><br></pre></td></tr></table></figure>

<p><code>kernel/proc.c</code>加<code>processNum</code>函数：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">uint64 <span class="title">processNum</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">proc</span> *<span class="title">p</span>;</span></span><br><span class="line">	uint64 cnt = <span class="number">0</span>;</span><br><span class="line">	<span class="keyword">for</span> (p = proc; p &lt; proc[NPROC]; p++)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">if</span> (p-&gt;state != UNUSED)</span><br><span class="line">		&#123;</span><br><span class="line">			cnt++;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> cnt;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>kalloc.c</code>加<code>getFreeMemory</code>函数：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">uint64 <span class="title">getFreeMemory</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">int</span> num = <span class="number">0</span>;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">run</span> *<span class="title">r</span>;</span></span><br><span class="line">	<span class="keyword">for</span> (r = kmem.freelist; r; r = r-&gt;next, num++)</span><br><span class="line">		;</span><br><span class="line">	<span class="keyword">return</span> num * PGSIZE;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>之后在<code>defs.h</code>中添加声明</p>
<p><code>sysproc.c</code>加<code>sys_sysinfo</code>函数：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">uint64 <span class="title">sys_sysinfo</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">sysinfo</span> <span class="title">info</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">proc</span> *<span class="title">p</span> =</span> myproc();</span><br><span class="line">	uint64 addr;</span><br><span class="line">	<span class="keyword">if</span> (argaddr(<span class="number">0</span>, &amp;addr) &lt; <span class="number">0</span>)</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	info.freemem = getFreememory();</span><br><span class="line">	info.nproc = processNum();</span><br><span class="line">	<span class="keyword">if</span> (copyout(p-&gt;pagetable, addr, (<span class="keyword">char</span> *)&amp;info, <span class="keyword">sizeof</span>(info)) &lt; <span class="number">0</span>)</span><br><span class="line">		<span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><img src="/2022/07/10/2022-7-10-oslab/image-20220720142621715.png" alt="image-20220720142621715"></p>
<h1 id="Lab3"><a href="#Lab3" class="headerlink" title="Lab3"></a>Lab3</h1><blockquote>
<p>  指导书：<a target="_blank" rel="noopener" href="https://pdos.csail.mit.edu/6.828/2020/labs/pgtbl.html">https://pdos.csail.mit.edu/6.828/2020/labs/pgtbl.html</a></p>
</blockquote>
<h2 id="Print-a-page-table"><a href="#Print-a-page-table" class="headerlink" title="Print a page table"></a>Print a page table</h2><p>打印页表的一些信息，用来帮助调试的。</p>
<blockquote>
<p>  Define a function called <code>vmprint()</code>. It should take a <code>pagetable_t</code> argument, and print that pagetable in the format described below. Insert <code>if(p-&gt;pid==1) vmprint(p-&gt;pagetable)</code> in exec.c just before the <code>return argc</code>, to print the first process’s page table. You receive full credit for this assignment if you pass the <code>pte printout</code> test of <code>make grade</code>.</p>
</blockquote>
<blockquote>
<p>  第一行显示vmprint的参数。之后，每个PTE都有一行，包括引用树中更深的页-表-页的PTE。每个PTE行由若干“.”缩进这表明它在树中的深度。每个PTE行显示其页面表页面中的PTE索引、PTE位和从PTE提取的物理地址。不要打印无效的PTE。在上例中，顶级页面table页面具有条目0和255的映射。条目0的下一级仅映射了索引0，该索引0的底层映射了条目0、1和2。</p>
</blockquote>
<ul>
<li><p><code>defs.c</code>中加vmprint定义</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">vmprint</span><span class="params">(<span class="keyword">pagetable_t</span>)</span></span>;</span><br></pre></td></tr></table></figure>
</li>
<li><p><code>kernel/exec.c</code>：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// exec.c</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span></span></span><br><span class="line"><span class="function"><span class="title">exec</span><span class="params">(<span class="keyword">char</span> *path, <span class="keyword">char</span> **argv)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">// ......</span></span><br><span class="line">  vmprint(p-&gt;pagetable); <span class="comment">// 按照实验要求，在 exec 返回之前打印一下页表。</span></span><br><span class="line">  <span class="keyword">return</span> argc; <span class="comment">// this ends up in a0, the first argument to main(argc, argv)</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>在<code>kernel/vm.c</code>中写<code>vmprint()</code></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">vmprintwalk</span><span class="params">(<span class="keyword">pagetable_t</span> pagetable, <span class="keyword">int</span> deep)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">512</span>; i++)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="comment">// 2^9 PTEs in a page table</span></span><br><span class="line">		<span class="keyword">pte_t</span> pte = pagetable[i];</span><br><span class="line">		<span class="keyword">if</span> (pte &amp; PTE_V)</span><br><span class="line">		&#123;</span><br><span class="line">			<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt;= deep; ++i)</span><br><span class="line">			&#123;</span><br><span class="line">				<span class="built_in">printf</span>(<span class="string">&quot;.. &quot;</span>);</span><br><span class="line">			&#125;</span><br><span class="line">			<span class="built_in">printf</span>(<span class="string">&quot;%d: pte %p pa %p\n&quot;</span>, i, pte, PTE2PA(pte));</span><br><span class="line">			<span class="keyword">if</span> ((pte &amp; (PTE_R | PTE_W | PTE_X)) == <span class="number">0</span>)</span><br><span class="line">			&#123;</span><br><span class="line">				<span class="comment">// this PTE points to a lower-level page table.</span></span><br><span class="line">				uint64 child = PTE2PA(pte);</span><br><span class="line">				vmprintwalk((<span class="keyword">pagetable_t</span>)child, deep + <span class="number">1</span>);</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">vmprint</span><span class="params">(<span class="keyword">pagetable_t</span> pagetable)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="built_in">printf</span>(<span class="string">&quot;page table %p\n&quot;</span>, pagetable);</span><br><span class="line">	vmprintwalk(pagetable, <span class="number">0</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<p><img src="/2022/07/10/2022-7-10-oslab/image-20220721150757704.png" alt="image-20220721150757704"></p>
<h2 id="A-kernel-page-table-per-process"><a href="#A-kernel-page-table-per-process" class="headerlink" title="A kernel page table per process"></a>A kernel page table per process</h2><blockquote>
<p>  Xv6有一个单独的内核页表，每当它在内核中执行时都会使用它。内核页表是物理地址的直接映射，因此内核虚拟地址x映射到物理地址x。Xv6还为每个进程的用户地址空间提供了一个单独的页表，仅包含该进程用户内存的映射，从虚拟地址零开始。因为内核页表不包含这些映射，所以用户地址在内核中无效。因此，当内核需要使用在系统调用中传递的用户指针（例如，传递给write()的缓冲区指针）时，内核必须首先将指针转换为物理地址。本节和下一节的目标是允许内核直接解引用用户指针。</p>
<p>  您的第一项工作是修改内核，使每个进程在内核中执行时都使用自己的内核页表副本。修改struct proc以维护每个进程的内核页表，并修改调度器以在切换进程时切换内核页表。对于这一步，每个进程内核页表应该与现有的全局内核页表相同。如果usertests运行正确，则通过这部分实验室。</p>
</blockquote>
<p>本 Lab 目标是让每一个进程进入内核态后，都能有自己的独立<strong>内核页表</strong>，为第三个实验做准备。</p>
<ul>
<li><p>在进程结构体proc中加kernelpgtbl字段，用于存储进程专享的内核态页表。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// kernel/proc.h</span></span><br><span class="line"><span class="comment">// Per-process state</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">proc</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">spinlock</span> <span class="title">lock</span>;</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// p-&gt;lock must be held when using these:</span></span><br><span class="line">  <span class="class"><span class="keyword">enum</span> <span class="title">procstate</span> <span class="title">state</span>;</span> <span class="comment">// Process state</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">proc</span> *<span class="title">parent</span>;</span>  <span class="comment">// Parent process</span></span><br><span class="line">  <span class="keyword">void</span> *chan;           <span class="comment">// If non-zero, sleeping on chan</span></span><br><span class="line">  <span class="keyword">int</span> killed;           <span class="comment">// If non-zero, have been killed</span></span><br><span class="line">  <span class="keyword">int</span> xstate;           <span class="comment">// Exit status to be returned to parent&#x27;s wait</span></span><br><span class="line">  <span class="keyword">int</span> pid;              <span class="comment">// Process ID</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// these are private to the process, so p-&gt;lock need not be held.</span></span><br><span class="line">  uint64 kstack;               <span class="comment">// Virtual address of kernel stack</span></span><br><span class="line">  uint64 sz;                   <span class="comment">// Size of process memory (bytes)</span></span><br><span class="line">  <span class="keyword">pagetable_t</span> pagetable;       <span class="comment">// User page table</span></span><br><span class="line">  <span class="keyword">pagetable_t</span> kernelPageTable; <span class="comment">// Kernel page table</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">trapframe</span> *<span class="title">trapframe</span>;</span> <span class="comment">// data page for trampoline.S</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">context</span> <span class="title">context</span>;</span>      <span class="comment">// swtch() here to run process</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">file</span> *<span class="title">ofile</span>[<span class="title">NOFILE</span>];</span>  <span class="comment">// Open files</span></span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">inode</span> *<span class="title">cwd</span>;</span>           <span class="comment">// Current directory</span></span><br><span class="line">  <span class="keyword">char</span> name[<span class="number">16</span>];               <span class="comment">// Process name (debugging)</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
<li><p>之后是初始化这个<code>kernelPageTable</code>字段，仿<code>kernel/vm.c</code>里<code>kvminit</code>函数，用内核自己pagetable初始化的方式初始化用户进程的<code>kernel pagetable</code>，其中<code>uvmmap</code>类似于<code>kvmmap</code>，只不过<code>kvmmap</code>是直接对全局的<code>kernel_pagetable</code>进行<code>mappage</code>，而<code>uvmmap</code>并没有指定page table</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">pagetable_t</span> <span class="title">proc_kvminit</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="comment">// kernel_pagetable = (pagetable_t)kalloc();</span></span><br><span class="line">	<span class="comment">// memset(kernel_pagetable, 0, PGSIZE);</span></span><br><span class="line">	<span class="keyword">pagetable_t</span> kernelPageTable;</span><br><span class="line">	kernelPageTable = uvmcreate();</span><br><span class="line">	<span class="keyword">if</span> (kernelPageTable == <span class="number">0</span>)</span><br><span class="line">		<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">	uvmmap(UART0, UART0, PGSIZE, PTE_R | PTE_W);</span><br><span class="line">	uvmmap(VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);</span><br><span class="line">	uvmmap(CLINT, CLINT, <span class="number">0x10000</span>, PTE_R | PTE_W);</span><br><span class="line">	uvmmap(PLIC, PLIC, <span class="number">0x400000</span>, PTE_R | PTE_W);</span><br><span class="line">	uvmmap(KERNBASE, KERNBASE, (uint64)etext - KERNBASE, PTE_R | PTE_X);</span><br><span class="line">	uvmmap((uint64)etext, (uint64)etext, PHYSTOP - (uint64)etext, PTE_R | PTE_W);</span><br><span class="line">	uvmmap(TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X);</span><br><span class="line">	<span class="keyword">return</span> kernelPageTable;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">uvmmap</span><span class="params">(uint64 va, uint64 pa, uint64 sz, <span class="keyword">int</span> perm)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">if</span> (mappages(kernel_pagetable, va, sz, pa, perm) != <span class="number">0</span>)</span><br><span class="line">		panic(<span class="string">&quot;uvmmap&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>在defs.h加声明</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">pagetable_t</span>     <span class="title">proc_kvminit</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br></pre></td></tr></table></figure>
</li>
<li><p>在<code>kernel/proc.c</code>中的<code>allocproc</code>函数中添加调用<code>proc_kvminit()</code>的代码段</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">p-&gt;kernelPageTable = proc_kvminit();</span><br><span class="line"><span class="keyword">if</span> (p-&gt;kernelPageTable == <span class="number">0</span>)</span><br><span class="line">&#123;</span><br><span class="line">	freeproc(p);</span><br><span class="line">	release(&amp;p-&gt;lock);</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>接下来是初始化内核栈，内核栈的初始化原来是在 <code>kernel/proc.c</code> 中的 <code>procinit</code> 函数内，这部分要求将函数内的代码转移到 <code>allocproc</code> 函数内，因此在上一步初始化内核态页表的代码下面接着添加初始化内核栈的代码：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">p-&gt;kernelPageTable = proc_kvminit();</span><br><span class="line"><span class="keyword">if</span> (p-&gt;kernelPageTable == <span class="number">0</span>)</span><br><span class="line">&#123;</span><br><span class="line">	freeproc(p);</span><br><span class="line">	release(&amp;p-&gt;lock);</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 初始化内核栈</span></span><br><span class="line"><span class="keyword">char</span> *pa = kalloc();</span><br><span class="line"><span class="keyword">if</span> (pa == <span class="number">0</span>)</span><br><span class="line">	panic(<span class="string">&quot;kalloc&quot;</span>);</span><br><span class="line">uint64 va = KSTACK((<span class="keyword">int</span>)(p - proc));</span><br><span class="line">uvmmap(va, (uint64)pa, PGSIZE, PTE_R | PTE_W);</span><br><span class="line">p-&gt;kstack = va;</span><br></pre></td></tr></table></figure>
</li>
<li><p>进程调度时，切换内核页：内核页的管理使用的是 SATP 寄存器，在 <code>kernel/proc.c</code> 的调度函数 <code>scheduler</code> 中添加切换 SATP 寄存器的代码，并在调度后切换回来, <code>w_satp()</code> 函数用于设置最高级页目录地址的寄存器 SATP, <code>sfence_vam()</code> 用于清空当前 TLB.</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// change satp</span></span><br><span class="line">w_satp(MAKE_SATP(p-&gt;kernelPageTable));</span><br><span class="line">sfence_vma();</span><br><span class="line"><span class="comment">// change process</span></span><br><span class="line">swtch(&amp;c-&gt;context, &amp;p-&gt;context);</span><br><span class="line"><span class="comment">// change back</span></span><br><span class="line">kvminithart();</span><br></pre></td></tr></table></figure>
</li>
<li><p>释放内核页表：直接遍历所有的页表，释放所有有效的页表项即可。仿照 <code>freewalk</code> 函数。仅释放页表的映射关系即可，不能将真实的物理地址也释放了。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">proc_freewalk</span><span class="params">(<span class="keyword">pagetable_t</span> pagetable)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="comment">// there are 2^9 = 512 PTEs in a page table.</span></span><br><span class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">512</span>; i++)</span><br><span class="line">	&#123;</span><br><span class="line">		<span class="keyword">pte_t</span> pte = pagetable[i];</span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span> (pte &amp; PTE_V)</span><br><span class="line">		&#123;</span><br><span class="line">			pagetable[i] = <span class="number">0</span>;</span><br><span class="line">			<span class="keyword">if</span> ((pte &amp; PTE_V) &amp;&amp; (pte &amp; (PTE_R | PTE_W | PTE_X)) == <span class="number">0</span>)</span><br><span class="line">			&#123;</span><br><span class="line">				<span class="comment">// this PTE points to a lower-level page table.</span></span><br><span class="line">				uint64 child = PTE2PA(pte);</span><br><span class="line">				proc_freewalk((<span class="keyword">pagetable_t</span>)child);</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	kfree((<span class="keyword">void</span> *)pagetable);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p><code>freeproc()</code> 代码如下, 还需注意的一点是, 内核栈 <code>p-&gt;stack</code> 需要在内核页表 <code>p-&gt;kpagetable</code> 之前清除.</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">void</span></span></span><br><span class="line"><span class="function"><span class="title">freeproc</span><span class="params">(struct proc *p)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	<span class="keyword">if</span> (p-&gt;trapframe)</span><br><span class="line">		kfree((<span class="keyword">void</span> *)p-&gt;trapframe);</span><br><span class="line">	p-&gt;trapframe = <span class="number">0</span>;</span><br><span class="line">	<span class="keyword">if</span> (p-&gt;pagetable)</span><br><span class="line">		proc_freepagetable(p-&gt;pagetable, p-&gt;sz);</span><br><span class="line">	p-&gt;pagetable = <span class="number">0</span>;</span><br><span class="line">	p-&gt;sz = <span class="number">0</span>;</span><br><span class="line">	p-&gt;pid = <span class="number">0</span>;</span><br><span class="line">	p-&gt;parent = <span class="number">0</span>;</span><br><span class="line">	p-&gt;name[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">	p-&gt;chan = <span class="number">0</span>;</span><br><span class="line">	p-&gt;killed = <span class="number">0</span>;</span><br><span class="line">	p-&gt;xstate = <span class="number">0</span>;</span><br><span class="line">	<span class="comment">// free kernel stack</span></span><br><span class="line">	<span class="keyword">if</span> (p-&gt;kstack)</span><br><span class="line">		uvmunmap(p-&gt;kernelPageTable, p-&gt;kstack, <span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line">	p-&gt;kstack = <span class="number">0</span>;</span><br><span class="line">	<span class="keyword">if</span> (p-&gt;kernelPageTable)</span><br><span class="line">		proc_freewalk(p-&gt;kernelPageTable);</span><br><span class="line">	p-&gt;kernelPageTable = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">	p-&gt;state = UNUSED;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
<li><p>在 vm.c 中添加头文件：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;spinlock.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&quot;proc.h&quot;</span></span></span><br></pre></td></tr></table></figure>
</li>
<li><p><code>kvmpa()</code> 函数用于将内核虚拟地址转换为物理地址, 其中调用 <code>walk()</code> 函数时使用了全局的内核页表. 此时需要换位当前进程的内核页表. </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">uint64</span></span><br><span class="line"><span class="function"><span class="title">kvmpa</span><span class="params">(uint64 va)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">	uint64 off = va % PGSIZE;</span><br><span class="line">	<span class="keyword">pte_t</span> *pte;</span><br><span class="line">	uint64 pa;</span><br><span class="line"></span><br><span class="line">	pte = walk(myproc()-&gt;kernelPageTable, va, <span class="number">0</span>);<span class="comment">//here</span></span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> (pte == <span class="number">0</span>)</span><br><span class="line">		panic(<span class="string">&quot;kvmpa&quot;</span>);</span><br><span class="line">	<span class="keyword">if</span> ((*pte &amp; PTE_V) == <span class="number">0</span>)</span><br><span class="line">		panic(<span class="string">&quot;kvmpa&quot;</span>);</span><br><span class="line">	pa = PTE2PA(*pte);</span><br><span class="line">	<span class="keyword">return</span> pa + off;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>

                                                                    </div>
                                                                    
                                                                        <div class="prev-or-next">
                                                                            <div class="post-foot-next">
                                                                                
                                                                                    <a href="/2022/07/07/6.s081/" target="_self">
                                                                                        <i class="iconfont icon-chevronleft"></i>
                                                                                        <span>Prev</span>
                                                                                    </a>
                                                                                    
                                                                            </div>
                                                                            <div class="post-attach">
                                                                                <!-- <span class="post-pubtime">
              <i class="iconfont icon-updatetime" title="Update time"></i>
              2022-07-10
            </span> -->

                                                                                
                                                                                            <span class="post-categories">
          <!-- <i class="iconfont icon-bookmark" title="Categories"></i> -->
          
          <!-- <span class="span--category">
            <a href="/categories/Technology/" title="Technology">
              <b>#</b> Technology
            </a>
          </span> -->
                                                                                            
                                                                                                </span>
                                                                                                
                                                                                    <span class="post-tags">
          <!-- <i class="iconfont icon-tags" title="Tags"></i> -->
          
          <!-- <span class="span--tag">
            <a href="/tags/OS/" title="OS">
              <b>#</b> OS
            </a>
          </span> -->
                                                                                    
                                                                                        </span>
                                                                                        
                                                                            </div>
                                                                            <div class="post-foot-prev">
                                                                                
                                                                                    <a href="/2022/07/12/XV6/" target="_self">
                                                                                        <span>Next</span>
                                                                                        <i class="iconfont icon-chevronright"></i>
                                                                                    </a>
                                                                                    
                                                                            </div>
                                                                        </div>
                                                                        
                                                                </div>
                                                                
  <div id="btn-catalog" class="btn-catalog">
    <i class="iconfont icon-catalog"></i>
  </div>
  <div class="post-catalog hidden" id="catalog">
    <div class="title">Contents</div>
    <div class="catalog-content">
      
        <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E8%BF%9B%E5%BA%A6"><span class="toc-text">进度</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%8E%AF%E5%A2%83"><span class="toc-text">环境</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%88%86%E6%94%AF%E5%BB%BA%E8%AE%AE%EF%BC%9A"><span class="toc-text">分支建议：</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#lab1"><span class="toc-text">lab1</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#sleep"><span class="toc-text">sleep</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#pingpong"><span class="toc-text">pingpong</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#prime"><span class="toc-text">prime</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Lab2-system-calls"><span class="toc-text">Lab2 system calls</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#System-call-tracing"><span class="toc-text">System call tracing</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#hints"><span class="toc-text">hints</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Sysinfo"><span class="toc-text">Sysinfo</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Lab3"><span class="toc-text">Lab3</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#Print-a-page-table"><span class="toc-text">Print a page table</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#A-kernel-page-table-per-process"><span class="toc-text">A kernel page table per process</span></a></li></ol></li></ol>
      
    </div>
  </div>

  
<script src="/js/catalog.js"></script>




                                                                    
                                                                        <div class="comments-container">
                                                                            







                                                                        </div>
                                                                        
                                                            </div>
                                                            
        
<div class="footer">
  <div class="social">
    <ul>
      
        <li>
          <a title="github" target="_blank" rel="noopener" href="https://github.com/Ghostasky">
            <i class="iconfont icon-github"></i>
          </a>
        </li>
      
        <li>
          <a title="twitter" target="_blank" rel="noopener" href="https://twitter.com/ghostasky">
            <i class="iconfont icon-twitter"></i>
          </a>
        </li>
      
    </ul>
  </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/Ghostasky">怕什么真理无穷，进一寸有进一寸的欢喜。</a>
        
    </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/zchengsite/hexo-theme-oranges">Copyright © 2022 Oranges</a>
        
    </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/zchengsite/hexo-theme-oranges">Theme by Oranges | Powered by Hexo</a>
        
    </div>
  
</div>

      </div>

      <div class="tools-bar">
        <div class="back-to-top tools-bar-item hidden">
  <a href="javascript: void(0)">
    <i class="iconfont icon-chevronup"></i>
  </a>
</div>


<script src="/js/backtotop.js"></script>



        
  <div class="search-icon tools-bar-item" id="search-icon">
    <a href="javascript: void(0)">
      <i class="iconfont icon-search"></i>
    </a>
  </div>

  <div class="search-overlay hidden">
    <div class="search-content" tabindex="0">
      <div class="search-title">
        <span class="search-icon-input">
          <a href="javascript: void(0)">
            <i class="iconfont icon-search"></i>
          </a>
        </span>
        
          <input type="text" class="search-input" id="search-input" placeholder="Search...">
        
        <span class="search-close-icon" id="search-close-icon">
          <a href="javascript: void(0)">
            <i class="iconfont icon-close"></i>
          </a>
        </span>
      </div>
      <div class="search-result" id="search-result"></div>
    </div>
  </div>

  <script type="text/javascript">
    var inputArea = document.querySelector("#search-input")
    var searchOverlayArea = document.querySelector(".search-overlay")

    inputArea.onclick = function() {
      getSearchFile()
      this.onclick = null
    }

    inputArea.onkeydown = function() {
      if(event.keyCode == 13)
        return false
    }

    function openOrHideSearchContent() {
      let isHidden = searchOverlayArea.classList.contains('hidden')
      if (isHidden) {
        searchOverlayArea.classList.remove('hidden')
        document.body.classList.add('hidden')
        // inputArea.focus()
      } else {
        searchOverlayArea.classList.add('hidden')
        document.body.classList.remove('hidden')
      }
    }

    function blurSearchContent(e) {
      if (e.target === searchOverlayArea) {
        openOrHideSearchContent()
      }
    }

    document.querySelector("#search-icon").addEventListener("click", openOrHideSearchContent, false)
    document.querySelector("#search-close-icon").addEventListener("click", openOrHideSearchContent, false)
    searchOverlayArea.addEventListener("click", blurSearchContent, false)

    var searchFunc = function (path, search_id, content_id) {
      'use strict';
      var $input = document.getElementById(search_id);
      var $resultContent = document.getElementById(content_id);
      $resultContent.innerHTML = "<ul><span class='local-search-empty'>First search, index file loading, please wait...<span></ul>";
      $.ajax({
        // 0x01. load xml file
        url: path,
        dataType: "xml",
        success: function (xmlResponse) {
          // 0x02. parse xml file
          var datas = $("entry", xmlResponse).map(function () {
            return {
              title: $("title", this).text(),
              content: $("content", this).text(),
              url: $("url", this).text()
            };
          }).get();
          $resultContent.innerHTML = "";

          $input.addEventListener('input', function () {
            // 0x03. parse query to keywords list
            var str = '<ul class=\"search-result-list\">';
            var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
            $resultContent.innerHTML = "";
            if (this.value.trim().length <= 0) {
              return;
            }
            // 0x04. perform local searching
            datas.forEach(function (data) {
              var isMatch = true;
              var content_index = [];
              if (!data.title || data.title.trim() === '') {
                data.title = "Untitled";
              }
              var orig_data_title = data.title.trim();
              var data_title = orig_data_title.toLowerCase();
              var orig_data_content = data.content.trim().replace(/<[^>]+>/g, "");
              var data_content = orig_data_content.toLowerCase();
              var data_url = data.url;
              var index_title = -1;
              var index_content = -1;
              var first_occur = -1;
              // only match artiles with not empty contents
              if (data_content !== '') {
                keywords.forEach(function (keyword, i) {
                  index_title = data_title.indexOf(keyword);
                  index_content = data_content.indexOf(keyword);

                  if (index_title < 0 && index_content < 0) {
                    isMatch = false;
                  } else {
                    if (index_content < 0) {
                      index_content = 0;
                    }
                    if (i == 0) {
                      first_occur = index_content;
                    }
                    // content_index.push({index_content:index_content, keyword_len:keyword_len});
                  }
                });
              } else {
                isMatch = false;
              }
              // 0x05. show search results
              if (isMatch) {
                str += "<li><a href='" + data_url + "' class='search-result-title'>" + orig_data_title + "</a>";
                var content = orig_data_content;
                if (first_occur >= 0) {
                  // cut out 100 characters
                  var start = first_occur - 20;
                  var end = first_occur + 80;

                  if (start < 0) {
                    start = 0;
                  }

                  if (start == 0) {
                    end = 100;
                  }

                  if (end > content.length) {
                    end = content.length;
                  }

                  var match_content = content.substr(start, end);

                  // highlight all keywords
                  keywords.forEach(function (keyword) {
                    var regS = new RegExp(keyword, "gi");
                    match_content = match_content.replace(regS, "<span class=\"search-keyword\">" + keyword + "</span>");
                  });

                  str += "<p class=\"search-result-abstract\">" + match_content + "...</p>"
                }
                str += "</li>";
              }
            });
            str += "</ul>";
            if (str.indexOf('<li>') === -1) {
              return $resultContent.innerHTML = "<ul><span class='local-search-empty'>No result<span></ul>";
            }
            $resultContent.innerHTML = str;
          });
        },
        error: function(xhr, status, error) {
          $resultContent.innerHTML = ""
          if (xhr.status === 404) {
            $resultContent.innerHTML = "<ul><span class='local-search-empty'>The search.xml file was not found, please refer to：<a href='https://github.com/zchengsite/hexo-theme-oranges#configuration' target='_black'>configuration</a><span></ul>";
          } else {
            $resultContent.innerHTML = "<ul><span class='local-search-empty'>The request failed, Try to refresh the page or try again later.<span></ul>";
          }
        }
      });
      $(document).on('click', '#search-close-icon', function() {
        $('#search-input').val('');
        $('#search-result').html('');
      });
    }

    var getSearchFile = function() {
        var path = "/search.xml";
        searchFunc(path, 'search-input', 'search-result');
    }
  </script>




        
  <div class="tools-bar-item theme-icon" id="switch-color-scheme">
    <a href="javascript: void(0)">
      <i id="theme-icon" class="iconfont icon-moon"></i>
    </a>
  </div>

  
<script src="/js/colorscheme.js"></script>





        
  
    <div class="share-icon tools-bar-item">
      <a href="javascript: void(0)" id="share-icon">
        <i class="iconfont iconshare"></i>
      </a>
      <div class="share-content hidden">
        
          <a class="share-item" href="https://twitter.com/intent/tweet?text=' + MIT6S081lab + '&url=' + https%3A%2F%2Fghostasky.github.io%2F2022%2F07%2F10%2F2022-7-10-oslab%2F + '" target="_blank" title="Twitter">
            <i class="iconfont icon-twitter"></i>
          </a>
        
        
          <a class="share-item" href="https://www.facebook.com/sharer.php?u=https://ghostasky.github.io/2022/07/10/2022-7-10-oslab/" target="_blank" title="Facebook">
            <i class="iconfont icon-facebooksquare"></i>
          </a>
        
      </div>
    </div>
  
  
<script src="/js/shares.js"></script>



      </div>
    </div>
  </body>
</html>
